<?php
/**
 * Copyright 2012  SURFfoundation
 * 
 * This file is part of ESCAPE.
 * 
 * ESCAPE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ESCAPE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ESCAPE.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For more information:
 * http://escapesurf.wordpress.com/
 * http://www.surffoundation.nl/
 * 
 * Contact: d.vierkant@utwente.nl
 * 
 * @license http://www.gnu.org/licenses/gpl.html GNU GPLv3
 */
?>
<?php
/**
 * User
 * 
 * Represents a user object.
 */
class escape_repository_User extends escape_repository_DataObject
{
	public static $predicate_mbox = 'http://xmlns.com/foaf/0.1/mbox';
	public static $predicate_name = 'http://xmlns.com/foaf/0.1/name';
	public static $predicate_organization = 'http://purl.utwente.nl/ns/escape-system.owl#organization';
	public static $predicate_dai = 'http://purl.org/info:eu-repo/dai#daiId';
	public static $predicate_open_id = 'http://xmlns.com/foaf/0.1/openid';
	public static $predicate_password_hash = 'http://purl.utwente.nl/ns/escape-system.owl#passwordHash';
	public static $predicate_data_source = 'http://purl.utwente.nl/ns/escape-system.owl#dataSource';
	public static $predicate_system_role = 'http://purl.utwente.nl/ns/escape-system.owl#systemRole';
	
	public static $role_administrator = 'http://purl.utwente.nl/ns/escape-system.owl#Administrator';
	public static $role_creator = 'http://purl.utwente.nl/ns/escape-system.owl#Creator';
	
	/**
	 * Constructs a user object.
	 * @param escape_repository_Repository $repository Link to the repository object
	 * @param string $uri The URI for the data object
	 * @param simplerdf_RdfResource $rdfResource Prefetched RDF data for object creation
	 * @param boolean $noIndex If true, do not use the index to fetch the object data
	 * @param boolean $allowDeleted If true, also return deleted objects
	 * @return escape_repository_User The user object
	 */
	public function __construct(&$repository, $uri, $rdfResource = null, $noIndex = false, $allowDeleted = false)
	{
		parent::__construct($repository, $uri, $rdfResource, $noIndex, $allowDeleted);
	}
	
	/**
	 * Get the title for this data objec using the title URIs specified in the repository schema.
	 * Overridden to automatically generate titles for user accounts based on the user name.
	 * @param boolean $returnAsTriple If true, return the title as a triple array
	 * @return string|array Title as a string or array with the keys 's', 'P' and 'o'
	 */
	public function getTitle($returnAsTriple = false)
	{
		if($this->titleTriple === null)
		{
			$this->titleTriple = array(
							's' => $this->getUri(),
							'P' => self::$predicate_name,
							'o' => $this->getName(),
						);
		}
						
		if(!$returnAsTriple)
		{
			return $this->titleTriple['o'];
		}
		else
		{
			return $this->titleTriple;
		}
	}
	
	/**
	 * Get the object ID (PID without the namespace part).
	 * @return string Object ID
	 */
	public function getId()
	{
		return $this->repository->convertObjectUriToUserObjectId($this->uri);
	}
	
	/**
	 * Get the username.
	 * @return string username
	 */
	public function getName()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getFirstObject(self::$predicate_name);
	}
	
	/**
	 * Set the username.
	 * @param string $name username
	 */
	public function setName($name)
	{
		$name = trim($name);
		
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_name);
		$rdfResource->addStatement(self::$predicate_name, $name);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Get the email address.
	 * @return string Email address
	 */
	public function getMbox()
	{
		$rdfResource = $this->getProperties();
		
		$mbox = $rdfResource->getFirstObject(self::$predicate_mbox);
		$mbox = str_replace('mailto:', '', $mbox);
		
		return $mbox;
	}
	
	/**
	 * Set the email address.
	 * @param string $mbox Email address
	 */
	public function setMbox($mbox)
	{
		$mbox = trim($mbox);
		
		if(!preg_match('/^mailto:/', $mbox))
		{
			$mbox = 'mailto:' . $mbox;
		}
		$mbox = mb_strtolower($mbox);
		
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_mbox);
		$rdfResource->addStatement(self::$predicate_mbox, $mbox);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Get the organization.
	 * @return string organization
	 */
	public function getOrganization()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getFirstObject(self::$predicate_organization);
	}
	
	/**
	 * Set the organization.
	 * @param string $organization organization
	 */
	public function setOrganization($organization)
	{
		$organization = trim($organization);
		
		$rdfResource = $this->getProperties();
		
		if($organization != $rdfResource->getFirstObject(self::$predicate_organization))
		{
			$rdfResource->removeStatement(self::$predicate_organization);
			if($organization != '')
			{
				$rdfResource->addStatement(self::$predicate_organization, $organization);
			}
			
			$this->setProperties($rdfResource);
		}
	}
	
	/**
	 * Get the DAI.
	 * @return string dai
	 */
	public function getDai()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getFirstObject(self::$predicate_dai);
	}
	
	/**
	 * Set the DAI.
	 * @param string $dai dai
	 */
	public function setDai($dai)
	{
		$dai = trim($dai);
		//TODO: check dai validity, automatically add prefix?
		
		$rdfResource = $this->getProperties();
		
		if($dai != $rdfResource->getFirstObject(self::$predicate_dai))
		{
			$rdfResource->removeStatement(self::$predicate_dai);
			if($dai != '')
			{
				$rdfResource->addStatement(self::$predicate_dai, $dai);
			}
			
			$this->setProperties($rdfResource);
		}
	}
	
	/**
	 * Get the data source.
	 * @return string data source
	 */
	public function getDataSource()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getFirstObject(self::$predicate_data_source);
	}
	
	/**
	 * Set the data source.
	 * @param string $dataSource data source
	 */
	public function setDataSource($dataSource)
	{
		$dataSource = trim($dataSource);
		
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_data_source);
		$rdfResource->addStatement(self::$predicate_data_source, $dataSource);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Get a list of OpenIDs connected to this account.
	 * @return array List of OpenIDs
	 */
	public function getOpenIds()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getObjects(self::$predicate_open_id);
	}
	
	/**
	 * Set the OpenIDs connected to this account.
	 * @param array $openIds List of OpenIDs
	 */
	public function setOpenIds($openIds)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_open_id);
		$rdfResource->addStatement(self::$predicate_open_id, $openIds);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Add an OpenID to this account.
	 * @param string $openId OpenId
	 */
	public function addOpenId($openId)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->addStatement(self::$predicate_open_id, $openId);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Remove an OpenID from this account.
	 * @param string $openId OpenId
	 */
	public function removeOpenId($openId)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_open_id, $openId);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Get all system roles.
	 * @param boolean $withLabels If true, the role URIs are returned as array keys, role labels are array values 
	 * @return array All system roles
	 */
	public static function getAllSystemRoles($withLabels = false)
	{
		$roleLabels = array(escape_repository_User::$role_administrator => 'Administrator', escape_repository_User::$role_creator => 'Creator');
		
		if($withLabels)
		{
			return $roleLabels;
		}
		else
		{
			return array_keys($roleLabels);
		}
	}

	/**
	 * Get the system roles assigned to this account.
	 * @param boolean $withLabels If true, the role URIs are returned as array keys, role labels are array values 
	 * @return array List of system roles
	 */
	public function getSystemRoles($withLabels = false)
	{
		$rdfResource = $this->getProperties();
		
		$roleLabels = $this->getAllSystemRoles(true);
		
		$roleUris = $rdfResource->getObjects(self::$predicate_system_role);
		if($withLabels)
		{
			$roles = array();
			foreach($roleUris as $roleUri)
			{
				$label = $roleLabels[$roleUri];
				if($label !== null)
				{
					$roles[$roleUri] = $label;
				}
				else
				{
					$roles[$roleUri] = $roleUri;
				}
			}
			
			return $roles;
		}
		else
		{
			return $roleUris;
		}
	}
	
	/**
	 * Check if this account has the system role specified.
	 * @param string $systemRole System role URI
	 * @return boolean True if this account has the system role specified
	 */
	public function hasSystemRole($systemRole)
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->hasStatement(self::$predicate_system_role, $systemRole);
	}
	
	/**
	 * Set the system roles for this account.
	 * @param array $systemRoles System role URIs
	 */
	public function setSystemRoles($systemRoles)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_system_role);
		$rdfResource->addStatement(self::$predicate_system_role, $systemRoles);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Add a system role to this account.
	 * @param string $systemRole System role URI
	 */
	public function addSystemRole($systemRole)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->addStatement(self::$predicate_system_role, $systemRole);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Remove a system role from this account.
	 * @param string $systemRole System role URI
	 */
	public function removeSystemRole($systemRole)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_system_role, $systemRole);
		
		$this->setProperties($rdfResource);
	}
	
	/**
	 * Set the password (stored as a SHA1 hash).
	 * @param string $password Password
	 */
	public function setPassword($password)
	{
		$rdfResource = $this->getProperties();
		
		$rdfResource->removeStatement(self::$predicate_password_hash);
		$rdfResource->addStatement(self::$predicate_password_hash, sha1($password));
		
		$this->setProperties($rdfResource);
	}

	/**
	 * Check if the account password is identical to the password specified.
	 * @param string $password Password
	 * @return boolean True if the account password is identical to the password specified
	 */
	public function checkPassword($password)
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->hasStatement(self::$predicate_password_hash, sha1($password));
	}

	/**
	 * Get the password hash.
	 * @return string password hash
	 */
	public function getPasswordHash()
	{
		$rdfResource = $this->getProperties();
		
		return $rdfResource->getFirstObject(self::$predicate_password_hash);
	}
	
	/**
	 * Get ORE aggregations where this user has the roles specified.
	 * @param array $roleUris Role URIs
	 * @return array Lisy of ORE aggregations
	 */
	public function getMyAggregations($roleUris)
	{
		$aggregations = array();
		
		if(count($roleUris) > 0)
		{
			$roleRestrictionPatterns = array();
			foreach($roleUris as $roleUri)
			{
				$roleRestrictionPatterns[] = "{?uri <" . $this->repository->tripleStore->sparqlEscapeUri($roleUri) . "> <" . $this->repository->tripleStore->sparqlEscapeUri($this->getUri()). "> .}";
			}
			$roleRestrictionPattern = implode(' UNION ', $roleRestrictionPatterns);
			
			$sparqlQuery  = "select ?uri\n";
			$sparqlQuery .= "where\n";
			$sparqlQuery .= "{\n";
			$sparqlQuery .= "	?uri <info:fedora/fedora-system:def/model#hasModel> <info:fedora/" . $this->repository->config['system_object_namespace'] . ":cmodel.ore.Aggregation> .\n";
			$sparqlQuery .= "	?uri <info:fedora/fedora-system:def/model#state> <info:fedora/fedora-system:def/model#Active> . \n";
			$sparqlQuery .= "	" . $roleRestrictionPattern . "\n";
			$sparqlQuery .= "}";
			
			$sparqlResultSet = $this->tripleStore->sparqlSelect($sparqlQuery);
			$results = $sparqlResultSet->getResults();
			
			foreach($results as $result)
			{
				$uri = $result['uri']['value']; 
				$aggregations[] = $this->repository->getOreAggregationByUri($uri);
			}
		}
		
		return $aggregations;
	}
	
}
